{
 "cells": [
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Create a search index in Azure AI Search using the Azure SDK for Python"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This notebook steps through creating, loading, and querying an index in Azure AI Search index by calling the azure-search-documents library in the Azure SDK for Python. "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Install packages and set variables"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "! pip install azure-search-documents==11.6.0b12 --quiet\n",
    "! pip install azure-identity --quiet\n",
    "! pip install python-dotenv --quiet"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Provide variables\n",
    "search_endpoint: str = \"PUT-YOUR-SEARCH-ENDPOINT-HERE\"\n",
    "search_api_key: str = \"PUT-YOUR-SEARCH-API-KEY-HERE\"\n",
    "index_name: str = \"hotels-quickstart-csharp\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Create an index"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from azure.core.credentials import AzureKeyCredential\n",
    "\n",
    "credential = AzureKeyCredential(search_api_key)\n",
    "\n",
    "from azure.search.documents.indexes import SearchIndexClient\n",
    "from azure.search.documents import SearchClient\n",
    "from azure.search.documents.indexes.models import (\n",
    "    ComplexField,\n",
    "    SimpleField,\n",
    "    SearchFieldDataType,\n",
    "    SearchableField,\n",
    "    SearchIndex\n",
    ")\n",
    "\n",
    "# Create a search schema\n",
    "index_client = SearchIndexClient(\n",
    "    endpoint=search_endpoint, credential=credential)\n",
    "fields = [\n",
    "        SimpleField(name=\"HotelId\", type=SearchFieldDataType.String, key=True),\n",
    "        SearchableField(name=\"HotelName\", type=SearchFieldDataType.String, sortable=True),\n",
    "        SearchableField(name=\"Description\", type=SearchFieldDataType.String, analyzer_name=\"en.lucene\"),\n",
    "        SearchableField(name=\"Category\", type=SearchFieldDataType.String, facetable=True, filterable=True, sortable=True),\n",
    "\n",
    "        SearchableField(name=\"Tags\", collection=True, type=SearchFieldDataType.String, facetable=True, filterable=True),\n",
    "\n",
    "        SimpleField(name=\"ParkingIncluded\", type=SearchFieldDataType.Boolean, facetable=True, filterable=True, sortable=True),\n",
    "        SimpleField(name=\"LastRenovationDate\", type=SearchFieldDataType.DateTimeOffset, facetable=True, filterable=True, sortable=True),\n",
    "        SimpleField(name=\"Rating\", type=SearchFieldDataType.Double, facetable=True, filterable=True, sortable=True),\n",
    "\n",
    "        ComplexField(name=\"Address\", fields=[\n",
    "            SearchableField(name=\"StreetAddress\", type=SearchFieldDataType.String),\n",
    "            SearchableField(name=\"City\", type=SearchFieldDataType.String, facetable=True, filterable=True, sortable=True),\n",
    "            SearchableField(name=\"StateProvince\", type=SearchFieldDataType.String, facetable=True, filterable=True, sortable=True),\n",
    "            SearchableField(name=\"PostalCode\", type=SearchFieldDataType.String, facetable=True, filterable=True, sortable=True),\n",
    "            SearchableField(name=\"Country\", type=SearchFieldDataType.String, facetable=True, filterable=True, sortable=True),\n",
    "        ])\n",
    "    ]\n",
    "\n",
    "scoring_profiles = []\n",
    "suggester = [{'name': 'sg', 'source_fields': ['Tags', 'Address/City', 'Address/Country']}]\n",
    "\n",
    "# Create the search index=\n",
    "index = SearchIndex(name=index_name, fields=fields, suggesters=suggester, scoring_profiles=scoring_profiles)\n",
    "result = index_client.create_or_update_index(index)\n",
    "print(f' {result.name} created')"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Create a documents payload"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Create a documents payload\n",
    "documents = [\n",
    "    {\n",
    "    \"@search.action\": \"upload\",\n",
    "    \"HotelId\": \"1\",\n",
    "    \"HotelName\": \"Stay-Kay City Hotel\",\n",
    "    \"Description\": \"This classic hotel is fully-refurbished and ideally located on the main commercial artery of the city in the heart of New York. A few minutes away is Times Square and the historic centre of the city, as well as other places of interest that make New York one of America's most attractive and cosmopolitan cities.\",\n",
    "    \"Category\": \"Boutique\",\n",
    "    \"Tags\": [ \"view\", \"air conditioning\", \"concierge\" ],\n",
    "    \"ParkingIncluded\": \"false\",\n",
    "    \"LastRenovationDate\": \"2020-01-18T00:00:00Z\",\n",
    "    \"Rating\": 3.60,\n",
    "    \"Address\": {\n",
    "        \"StreetAddress\": \"677 5th Ave\",\n",
    "        \"City\": \"New York\",\n",
    "        \"StateProvince\": \"NY\",\n",
    "        \"PostalCode\": \"10022\",\n",
    "        \"Country\": \"USA\"\n",
    "        }\n",
    "    },\n",
    "    {\n",
    "    \"@search.action\": \"upload\",\n",
    "    \"HotelId\": \"2\",\n",
    "    \"HotelName\": \"Old Century Hotel\",\n",
    "    \"Description\": \"The hotel is situated in a nineteenth century plaza, which has been expanded and renovated to the highest architectural standards to create a modern, functional and first-class hotel in which art and unique historical elements coexist with the most modern comforts. The hotel also regularly hosts events like wine tastings, beer dinners, and live music.\",\n",
    "    \"Category\": \"Boutique\",\n",
    "    \"Tags\": [ \"pool\", \"free wifi\", \"concierge\" ],\n",
    "    \"ParkingIncluded\": \"false\",\n",
    "    \"LastRenovationDate\": \"2019-02-18T00:00:00Z\",\n",
    "    \"Rating\": 3.60,\n",
    "    \"Address\": {\n",
    "        \"StreetAddress\": \"140 University Town Center Dr\",\n",
    "        \"City\": \"Sarasota\",\n",
    "        \"StateProvince\": \"FL\",\n",
    "        \"PostalCode\": \"34243\",\n",
    "        \"Country\": \"USA\"\n",
    "        }\n",
    "    },\n",
    "    {\n",
    "    \"@search.action\": \"upload\",\n",
    "    \"HotelId\": \"3\",\n",
    "    \"HotelName\": \"Gastronomic Landscape Hotel\",\n",
    "    \"Description\": \"The Gastronomic Hotel stands out for its culinary excellence under the management of William Dough, who advises on and oversees all of the Hotel’s restaurant services.\",\n",
    "    \"Category\": \"Suite\",\n",
    "    \"Tags\": [ \"restaurant\", \"bar\", \"continental breakfast\" ],\n",
    "    \"ParkingIncluded\": \"true\",\n",
    "    \"LastRenovationDate\": \"2015-09-20T00:00:00Z\",\n",
    "    \"Rating\": 4.80,\n",
    "    \"Address\": {\n",
    "        \"StreetAddress\": \"3393 Peachtree Rd\",\n",
    "        \"City\": \"Atlanta\",\n",
    "        \"StateProvince\": \"GA\",\n",
    "        \"PostalCode\": \"30326\",\n",
    "        \"Country\": \"USA\"\n",
    "        }\n",
    "    },\n",
    "    {\n",
    "    \"@search.action\": \"upload\",\n",
    "    \"HotelId\": \"4\",\n",
    "    \"HotelName\": \"Sublime Palace Hotel\",\n",
    "    \"Description\": \"Sublime Palace Hotel is located in the heart of the historic center of Sublime in an extremely vibrant and lively area within short walking distance to the sites and landmarks of the city and is surrounded by the extraordinary beauty of churches, buildings, shops and monuments. Sublime Cliff is part of a lovingly restored 19th century resort, updated for every modern convenience.\",\n",
    "    \"Category\": \"Boutique\",\n",
    "    \"Tags\": [ \"concierge\", \"view\", \"air conditioning\" ],\n",
    "    \"ParkingIncluded\": \"true\",\n",
    "    \"LastRenovationDate\": \"2020-02-06T00:00:00Z\",\n",
    "    \"Rating\": 4.60,\n",
    "    \"Address\": {\n",
    "        \"StreetAddress\": \"7400 San Pedro Ave\",\n",
    "        \"City\": \"San Antonio\",\n",
    "        \"StateProvince\": \"TX\",\n",
    "        \"PostalCode\": \"78216\",\n",
    "        \"Country\": \"USA\"\n",
    "        }\n",
    "    }\n",
    "]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Upload documents"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "search_client = SearchClient(endpoint=search_endpoint,\n",
    "                      index_name=index_name,\n",
    "                      credential=credential)\n",
    "try:\n",
    "    result = search_client.upload_documents(documents=documents)\n",
    "    print(\"Upload of new document succeeded: {}\".format(result[0].succeeded))\n",
    "except Exception as ex:\n",
    "    print (ex.message)\n",
    "\n",
    "    index_client = SearchIndexClient(\n",
    "    endpoint=search_endpoint, credential=credential)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Run your first query"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Run an empty query (returns selected fields, all documents)\n",
    "results =  search_client.search(query_type='simple',\n",
    "    search_text=\"*\" ,\n",
    "    select='HotelName,Description,Tags',\n",
    "    include_total_count=True)\n",
    "\n",
    "print ('Total Documents Matching Query:', results.get_count())\n",
    "for result in results:\n",
    "    print(result[\"@search.score\"])\n",
    "    print(result[\"HotelName\"])\n",
    "    print(result[\"Tags\"])\n",
    "    print(f\"Description: {result['Description']}\")\n"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Run a term query"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Run a term query\n",
    "results =  search_client.search(query_type='simple',\n",
    "    search_text=\"wifi\" ,\n",
    "    select='HotelName,Description,Tags',\n",
    "    include_total_count=True)\n",
    "\n",
    "print ('Total Documents Matching Query:', results.get_count())\n",
    "for result in results:\n",
    "    print(result[\"@search.score\"])\n",
    "    print(result[\"HotelName\"])\n",
    "    print(f\"Description: {result['Description']}\")"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Add a filter"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Add a filter\n",
    "results = search_client.search(\n",
    "    search_text=\"hotels\", \n",
    "    select='HotelId,HotelName,Rating', \n",
    "    filter='Rating gt 4', \n",
    "    order_by='Rating desc')\n",
    "\n",
    "for result in results:\n",
    "    print(\"{}: {} - {} rating\".format(result[\"HotelId\"], result[\"HotelName\"], result[\"Rating\"]))"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Scope a query to specific searchable fields"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "results = search_client.search(\n",
    "    search_text=\"sublime\", \n",
    "    search_fields=['HotelName'], \n",
    "    select='HotelId,HotelName')\n",
    "\n",
    "for result in results:\n",
    "    print(\"{}: {}\".format(result[\"HotelId\"], result[\"HotelName\"]))"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Return facets"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Return facets\n",
    "results = search_client.search(search_text=\"*\", facets=[\"Category\"])\n",
    "\n",
    "facets = results.get_facets()\n",
    "\n",
    "for facet in facets[\"Category\"]:\n",
    "    print(\"    {}\".format(facet))"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Look up a document "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Look up a specific document by ID\n",
    "result = search_client.get_document(key=\"3\")\n",
    "\n",
    "print(\"Details for hotel '3' are:\")\n",
    "print(\"Name: {}\".format(result[\"HotelName\"]))\n",
    "print(\"Rating: {}\".format(result[\"Rating\"]))\n",
    "print(\"Category: {}\".format(result[\"Category\"]))"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Autocomplete a query"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Autocomplete a query\n",
    "search_suggestion = 'sa'\n",
    "results = search_client.autocomplete(\n",
    "    search_text=search_suggestion, \n",
    "    suggester_name=\"sg\",\n",
    "    mode='twoTerms')\n",
    "\n",
    "print(\"Autocomplete for:\", search_suggestion)\n",
    "for result in results:\n",
    "    print (result['text'])"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Clean up\n",
    "\n",
    "If you are finished with this index, you can delete it by running the following lines. Deleting unnecessary indexes frees up space for stepping through more quickstarts and tutorials."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "try:\n",
    "    result = index_client.delete_index(index_name)\n",
    "    print ('Index', index_name, 'Deleted')\n",
    "except Exception as ex:\n",
    "    print (ex)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Confirm the index deletion by running the following script that lists all of the indexes on your search service. If hotels-quickstart is not listed, you've successfully deleted the index and have completed this quickstart."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "try:\n",
    "    result = index_client.get_index(index_name)\n",
    "    print (result)\n",
    "except Exception as ex:\n",
    "    print (ex)\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": ".venv",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.12"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
